package club.jdiy.dev.controller;

import club.jdiy.admin.freemarker.func.GetDictInfo;
import club.jdiy.admin.interceptor.GuestDisabled;
import club.jdiy.core.AppContext;
import club.jdiy.core.base.domain.DictInfo;
import club.jdiy.core.base.domain.Ret;
import club.jdiy.core.sql.Rs;
import club.jdiy.dev.entity.JDiyUi;
import club.jdiy.dev.meta.*;
import club.jdiy.dev.service.JDiyUiService;
import club.jdiy.dev.types.BtnActTpl;
import club.jdiy.dev.types.ColFormatTpl;
import club.jdiy.dev.types.JoinTypeTpl;
import club.jdiy.dev.types.OutTpl;
import club.jdiy.dev.view.*;
import club.jdiy.utils.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Controller
@RequestMapping("mgmt/JDiy")
public class JDiyViController extends JDiyUiCtrl<JDiyUi, JDiyUiService> implements JDiyController {
    @RequestMapping("{_referrerMenuId}/view.{opType}.{uid}")
    public String view(
            HttpServletResponse response,
            @PathVariable String _referrerMenuId,//来源主菜单(for权限控制/表单无用，与其它类型界面保持一致)
            @PathVariable String uid,
            @PathVariable String opType, //打开类型：dialog | tab
            @RequestParam(defaultValue = "0") String id,//单条数据修改
            @RequestParam Map<String, String> qo,
            ModelMap map
    ) throws Exception {
        map.put("_referrerMenuId", _referrerMenuId);
        map.put("opType", opType);
        map.put("queryParamsJson", JsonUtils.stringify(qo));

        ViewUiMeta uiMeta;
        try {
            uiMeta = service.getUiMeta(uid);
        } catch (Exception ex) {
            ex.printStackTrace();
            return Ret.direct(response, Ret.Type.msg, "<div style=\"margin:10px;color:red;\">目标界面配置有误，请跟踪控制台错误日志并检查！</div>");
        }

        Rs vo = appContext.getDao().rs(uiMeta.getMainTable(), id);
        if (vo.isNew())
            return Ret.direct(context.getResponse(), Ret.Type.msg, "目标信息不存在或已被删除(table:" + uiMeta.getMainTable() + ", id:" + id + ")");

        FtlParser parser = createFtlParser();
        parser.addVariable("qo", qo);
        parser.addVariable("vo", vo);

        preUiMeta(uiMeta, parser);

        Map<String, Rs> manyToOneCachedMap = new HashMap<>();
        ViewHandler handler = handlers.getHandler(uiMeta.getPageHandler(), ViewHandler.class).orElse(new DefaultViewHandler());

        for (ViewTdMeta vtm : uiMeta.getTds()) {
            if (vtm.getType() == null) continue;
            String idKey = vtm.getId();
            String v = vo.getString(vtm.getField());

            if (vtm.getJoinType() == JoinTypeTpl.manyToOne) {
                String k = vtm.getJoinTable() + "@" + vtm.getField() + v;
                Rs rs = manyToOneCachedMap.get(k);
                if (rs == null) {
                    rs = context.getDao().rs(vtm.getJoinTable(), v);
                    manyToOneCachedMap.put(k, rs);
                }
                v = rs.getString(vtm.getJoinField());
            } else if (vtm.getJoinType() == JoinTypeTpl.oneToMany) {
                vo.set(idKey, getManyString("select " + vtm.getJoinField() + " as ret from " + vtm.getJoinTable() +
                        " where " + vtm.getJoinRef() + "='" + vo.getString("id") + "'"));
                continue;
            } else if (vtm.getJoinType() == JoinTypeTpl.manyToMany) {
                vo.set(idKey, getManyString("select t." + vtm.getJoinField() + " as ret from " + vtm.getJoinTable() +
                        " t inner join " + vtm.getManyTable() + " r on t.id=r." + vtm.getManyField1() +
                        " where r." + vtm.getManyField0() + "='" + vo.getString("id") + "'"));
                continue;
            }

            switch (vtm.getType()) {
                case kv:
                    Map<String, DictInfo> _kvmap = kv2DictInfoMap(vtm.getKv());
                    if (_kvmap.containsKey(v)) {
                        vo.put(idKey, GetDictInfo.withColor(_kvmap.get(v)));
                    }
                    break;
                case dict:
                    context.getDict(vtm.getDictId(), v).ifPresent(di -> vo.put(idKey, GetDictInfo.withColor(di)));
                    break;
                case tree:
                    TreeUiMeta treeMeta = service.getUiMeta(vtm.getTreeId());
                    String selfId = Objects.equals(vo.getTable(), treeMeta.getMainTable()) ? vo.getString(vo.getPrimaryKey()) : null;
                    Rs treeNode = Objects.equals(vo.getTable(), treeMeta.getMainTable()) ? vo : context.getDao().rs(treeMeta.getMainTable(), v);
                    vo.set(idKey, getTreePathString(vtm.getTreeDisplay(), treeMeta, treeNode, selfId, false));
                    break;
                case tpl:
                    try {
                        String tps = parser.parse(vtm.getTpl());
                        vo.set(idKey, tps);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                default:
                    vo.put(vtm.getId(), v);
            }
        }

        if (uiMeta.getTabs() != null) {
            for (ViewTabMeta it : uiMeta.getTabs()) {
                if (StringUtils.isNotBlank(it.getGoPageParam()))
                    it.setGoPageParam(parser.parse(it.getGoPageParam().trim()));
                if (StringUtils.isNotBlank(it.getGoPageFilter()))
                    it.setGoPageFilter(Base64.getEncoder().encodeToString(parser.parse(it.getGoPageFilter().trim()).getBytes()));
            }
        }

        if (uiMeta.isBtn() && uiMeta.getBtns() != null) {
            List<ButtonMeta> __btnList = new ArrayList<>();
            for (ButtonMeta btn : uiMeta.getBtns()) {
                if (StringUtils.isEmpty(btn.getConditionShow()) || JDiyLsController.ifCondition(btn, uiMeta, vo, parser)) {
                    if (BtnActTpl.page == btn.getAct()) {
                        btn.setPageParam(parser.parse(btn.getPageParam()));
                    } else if (BtnActTpl.link == btn.getAct()) {
                        btn.setOutLink(parser.parse(btn.getOutLink()));
                    } else if (BtnActTpl.ajax == btn.getAct()) {
                        btn.setAjaxUrl(new UrlUtils(parser.parse(btn.getAjaxUrl())).set("id", vo.getString("id")).toString());
                    }
                    btn.setTitle(parser.parse(btn.getTitle()));
                    __btnList.add(btn);
                }
            }
            map.put("btnList", __btnList);
        }


        map.put("storeData", appContext.getStore(uiMeta.getMainTable(), vo.getString("id")));
        // handler.onView(vo, qo);
        map.put("vo", vo);
        map.put("uiMeta", uiMeta);
        return "view.render";
    }


    @GuestDisabled
    @RequestMapping("view.ajax.{uid}.{btnId}")
    @ResponseBody
    public Ret<?> do_ajax(@PathVariable String uid, @PathVariable String btnId, String[] id) {
        return super.do_ajax("view", uid, btnId, id);
    }

    @Resource
    private AppContext appContext;
    @Resource
    private Handlers handlers;
}
